package com.dhcc.DRGsHosp.weightInterval;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @title		:WeightInterval.java
 * @description	:计算权重区间
 * @author		:mazhaoyan
 * @date		:2016年3月3日
 * @version     :1.0
 * @copyright   :DHCC 2013-2014 
*/
public class WeightInterval {
	/**
	 * 
	 * @methodname    :calcWeightInterval
	 * @description   : 获取权重区间
	 * @param         : caseWeightList 病例权重List
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月3日
	 */
	public static double[] calcWeightInterval(List<Double> caseWeightList, int drgs)
	{
		int listSize = caseWeightList.size();//病例权重值个数
		Collections.sort(caseWeightList);//对病例权重进行升序排列
		
		//确定区间个数 [list数目要大于等于3个]
		if(drgs<3)
		{
			return null;
		}
		int intervalCnt = 3;//区间个数  默认是3个
		if(drgs>70)
		{
			intervalCnt = 4;
		}
		int intervalNum = listSize/intervalCnt;//每个区间的病例权重的数目 | 注意最后一个区间数目
		int[] intervalBumArr=new int[intervalCnt];
		for(int i = 0;i<intervalCnt-1;i++)
		{
			intervalBumArr[i] = intervalNum;
		}
		intervalBumArr[intervalCnt-1] = listSize - intervalNum*(intervalCnt-1);
		
		Map<String,Object> intervalMap = constructIntervalMap(caseWeightList,intervalBumArr);//存放各个区间段的数据
		
		//获取intervalCnt个聚类中心 及其每个聚类中心的个数
		Map<String,Object> centerMap = getClusterCenter(intervalMap);//这个是第一个聚类中心 

		//循环去计算最终的中心
		Map<String,Object> finalCenterMap = getFinalCenter(caseWeightList,centerMap);
		double[] breakPointArr =  getBreakPoints(caseWeightList,finalCenterMap);
		return breakPointArr;
		
	}
	public static void main(String[] args) {
		List<Double> tt = new ArrayList<Double>();
		tt.add(6.14);tt.add(4.3);tt.add(6.37);tt.add(3.87);tt.add(4.21);
		tt.add(8.27);tt.add(7.76);tt.add(4.28);tt.add(9.87);tt.add(9.14);
		tt.add(4.02);tt.add(4.08);tt.add(1.5);tt.add(7.06);tt.add(5.23);
		tt.add(3.01);tt.add(3.26);tt.add(5.69);tt.add(8.62);tt.add(1.24);
		tt.add(6.61);tt.add(4.59);tt.add(5.74);tt.add(3.43);tt.add(5.91);
		tt.add(4.54);tt.add(7.59);tt.add(4.65);tt.add(7.19);tt.add(1.03);
		tt.add(8.64);tt.add(2.77);tt.add(2.7);tt.add(3.69);tt.add(3.67);
		tt.add(5.12);tt.add(4.17);tt.add(7.25);tt.add(4.19);tt.add(8.69);
		tt.add(7.96);tt.add(5.42);tt.add(3.48);tt.add(2.91);tt.add(5.78);
		tt.add(4.16);tt.add(1.67);tt.add(9.6);tt.add(5.31);tt.add(1.77);
		tt.add(6.68);tt.add(9.7);tt.add(4.85);tt.add(5.75);tt.add(6.11);
		tt.add(2.37);tt.add(7.97);tt.add(3.71);tt.add(7.4);tt.add(9.01);
		tt.add(1.48);tt.add(3.83);tt.add(6.5);tt.add(9.29);tt.add(1.29);
		tt.add(2.13);tt.add(2.26);tt.add(7.22);tt.add(4.11);tt.add(1.25);
		tt.add(8.14);tt.add(5.41);tt.add(2.33);tt.add(9.02);tt.add(2.79);
		tt.add(2.12);tt.add(1.97);tt.add(3.61);tt.add(6.9);tt.add(2.56);
		tt.add(9.66);tt.add(8.68);tt.add(8.45);tt.add(6.06);tt.add(3.73);
		tt.add(8.97);tt.add(7.1);tt.add(6.15);tt.add(6.73);tt.add(2.18);
		tt.add(6.26);tt.add(1.36);tt.add(8.79);tt.add(4.36);tt.add(7.73);
		tt.add(4.8);tt.add(7.9);tt.add(3.4);tt.add(2.5);//tt.add(4.38);
		double[] d = calcWeightInterval(tt, 100);
		for(double s: d){
			System.out.println(s);
		}
	}
	/**
	 * 
	 * @methodname    :getClusterCenter
	 * @description   : 获取每个区间的中心
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月3日
	 */
	public static Map<String,Object>  getClusterCenter(Map<String,Object> intervalMap) {
		int cnt = intervalMap.size();
		Map<String,Object> centerMap = new HashMap<String,Object>();
		for(int i = 1;i<=cnt;i++)
		{
			List<Double> tmpList = (List<Double>) intervalMap.get(""+i);
			double avg = 0;
			int listSize = tmpList.size();
			for(int j = 0;j<listSize;j++)
			{
				avg = avg+tmpList.get(j);
			}
			avg = avg/listSize;
			Map<String,Object> tmpMap = new HashMap<String,Object>();
			tmpMap.put("centerValue",avg);//区间中心
			tmpMap.put("intervalNum",listSize);//区间病例数
			centerMap.put(""+i,tmpMap);
		}
		return centerMap;
	}
	/**
	 * 
	 * @methodname    :constructIntervalMap
	 * @description   : 获取不同区间的具体数据
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月3日
	 */
	public static Map<String,Object> constructIntervalMap(List<Double> caseWeightList,int[] intervalBumArr)
	{
		Map<String,Object> intervalMap = new HashMap<String,Object>();//存放各个区间段的数据
		int intervalCnt = intervalBumArr.length;
		int tmpNum = 0;
		 for(int i = 1;i <= intervalCnt;i++)
		{//前intervalCnt-1个区间  每个区间有intervalNum个数据
			if(i>1)
			{
				tmpNum = tmpNum + intervalBumArr[i-2];
			}
			List<Double> tmpList = new ArrayList<Double>();//临时list
			for(int j=0;j<intervalBumArr[i-1];j++)
			{
				tmpList.add(caseWeightList.get(tmpNum+j));
			}
			intervalMap.put(""+i,tmpList);
		}
		return intervalMap;
	}
	/**
	 * 
	 * @methodname    :getFinalCenter
	 * @description   : 递归获取最终的聚类中心
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月3日
	 */
	public static Map<String,Object> getFinalCenter(List<Double> caseWeightList,Map<String,Object> centerMap)
	{
		int intervalCnt = centerMap.size();
		int[] intervalBumArr=new int[intervalCnt];
		for(int i = 0;i<caseWeightList.size();i++)
		{
			int index = 1;
			double min = 9999;
			for(int j = 1;j<=intervalCnt;j++)
			{
				if(Math.abs(caseWeightList.get(i)-(double)((Map<String,Object>)centerMap.get(""+j)).get("centerValue"))<min)
				{
					min = Math.abs(caseWeightList.get(i)-(double)((Map<String,Object>)centerMap.get(""+j)).get("centerValue"));
					index = j;
				}
			}
			intervalBumArr[index-1] = intervalBumArr[index-1]+1;
		}
		for(int i=0; i<intervalCnt; i++){
			if(i<intervalCnt-1 && centerMap.get((i+1)+"").equals(centerMap.get((i+2)+""))){
				intervalBumArr[i] = intervalBumArr[i+1] = (intervalBumArr[i] + intervalBumArr[i+1])/2;
			}
		}
		Map<String,Object> intervalMap = constructIntervalMap(caseWeightList,intervalBumArr);
		Map<String,Object> newCenterMap = getClusterCenter(intervalMap);
		double sse = SSE(centerMap,newCenterMap);
		if(sse<0.01) {
			return newCenterMap;
		} else {
			try {
				return getFinalCenter(caseWeightList,newCenterMap);
			} catch (Exception e) {
				e.printStackTrace();
				return newCenterMap ;
			}
		}
	}

	/**
	 * 
	 * @methodname    :SSE
	 * @description   : 误差平方和---sum of the squared errors
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月3日
	 */
	public static double SSE(Map<String,Object> oldMap,Map<String,Object> newMap) {
		int intervalCnt = oldMap.size();
		double sse = 0;
		for(int i=1;i<=intervalCnt;i++)
		{
			sse = sse + Math.pow(((double)((Map<String,Object>)oldMap.get(""+i)).get("centerValue")-(double)((Map<String,Object>)newMap.get(""+i)).get("centerValue")),2);
		}
		return sse;
	}
	
	/**
	 * 
	 * @methodname    :getBreakPoints
	 * @description   : 获取区间的分界点
	 * @param         :
	 * @author        :mazhaoyan
	 * @return        :
	 * @date          :2016年3月3日
	 */
	public static double[] getBreakPoints(List<Double> caseWeightList,Map<String,Object> finalCenterMap)
	{
		int breakPointCnt = finalCenterMap.size()-1;
		int tmpCnt = 0;
		double[] breakPointArr = new double[breakPointCnt];
		for(int i = 0;i<breakPointCnt;i++)
		{
			tmpCnt = tmpCnt+(int)((Map<String,Object>)finalCenterMap.get(""+(i+1))).get("intervalNum");
			breakPointArr[i] = caseWeightList.get(tmpCnt);
		}
		return breakPointArr;
	}

}
